/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
* Worker.java
*
* Created on December 1, 2007, 9:05 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
 */
package genomemap.worker;

import gui.genomemap.event.event.WorkerInputEvent;
import gui.genomemap.event.event.WorkerInputListener;
import gui.genomemap.event.event.WorkerOutputEvent;
import gui.genomemap.event.event.WorkerOutputListener;

import javautil.swing.components.ProgressSupport;

import java.beans.PropertyChangeListener;

import javax.swing.event.EventListenerList;

/**
 * @author Susanta Tewari
 * @version 1.0
 */
public class Worker extends ProgressSupport {

    /**
     * the length of the progressfor this worker
     */
    private int progLength = 100;

    /**
     * the starting value of the progress bar for this worker.
     */
    private int progStartVal = 0;

    /**
     * the parent worker that is delegating a job to this child worker.  Propety
     * change listeners from the parent worker would be added to this child worker for
     * a chained working enviornment.
     */
    private Worker parentWorker = null;

    /** Field description */
    private Worker childWorker = null;

    /** Field description */
    private final EventListenerList workerInputList = new EventListenerList();

    /** Field description */
    private final EventListenerList workerOutputList = new EventListenerList();

    /**
     * Constructs ...
     */
    protected Worker() {}

    /**
     * the parent worker that is delegating a job to this child worker.  Propety
     * change listeners from the parent worker would be added to this child worker for
     * a chained working enviornment.
     *
     * @param newVal
     */
    public void setParentWorker(Worker newVal) {

        parentWorker = newVal;

        parentWorker.setChildWorker(this);
        addParentListeners();
    }

    /**
     * adds all the property change listeners from the parent worker to this child
     * worker.
     */
    void addParentListeners() {

        if (parentWorker != null) {


            // add property change listeners
            PropertyChangeListener[] listeners =
                parentWorker.propertySupport.getPropertyChangeListeners();

            for (PropertyChangeListener listener : listeners) {

                addPropertyChangeListener(listener);
            }


            // add workerInputListener
            WorkerInputListener[] parentInputListenerList =
                parentWorker.workerInputList.getListeners(WorkerInputListener.class);

            for (WorkerInputListener listener : parentInputListenerList) {

                addWorkerInputListener(listener);
            }


            // add workerOutputListener
            WorkerOutputListener[] parentOutputListenerList =
                parentWorker.workerOutputList.getListeners(WorkerOutputListener.class);

            for (WorkerOutputListener listener : parentOutputListenerList) {

                addWorkerOutputListener(listener);
            }
        }
    }

    void addWorkerInputListener(WorkerInputListener l) {
        workerInputList.add(WorkerInputListener.class, l);
    }

    public void removeWorkerInputListener(WorkerInputListener l) {
        workerInputList.remove(WorkerInputListener.class, l);
    }

    protected void fireWorkerInputEvent(WorkerInputEvent e) {

        if (e == null) return;

        Object[] listeners = workerInputList.getListenerList();


        // LIFO for (int i = listeners.length-2; i>=0; i-=2) {
        // FIFO strategy
        for (int i = 0; i <= listeners.length - 2; i += 2) {

            if (listeners[i] == WorkerInputListener.class) {

                switch (e.getType()) {

                    case WorkerInputEvent.COM_GLHOOD :
                        ((WorkerInputListener) listeners[i + 1]).doComGLHoodInput(e);

                        break;

                    case WorkerInputEvent.COM_PLHOOD :
                        ((WorkerInputListener) listeners[i + 1]).doComPLHoodInput(e);

                        break;

                    case WorkerInputEvent.COM_JLHOOD :
                        ((WorkerInputListener) listeners[i + 1]).doComJLHoodInput(e);

                        break;

                    case WorkerInputEvent.ANNEAL :
                        ((WorkerInputListener) listeners[i + 1]).doAnnealInput(e);

                        break;

                    case WorkerInputEvent.PROG_CURVE :
                        ((WorkerInputListener) listeners[i + 1]).doProgCurveInput(e);

                        break;
                }
            }
        }
    }

    public void addWorkerOutputListener(WorkerOutputListener l) {
        workerOutputList.add(WorkerOutputListener.class, l);
    }

    public void removeWorkerOutputListener(WorkerOutputListener l) {
        workerOutputList.remove(WorkerOutputListener.class, l);
    }

    void fireWorkerOutputEvent(WorkerOutputEvent e) {

        if (e == null) return;

        Object[] listeners = workerOutputList.getListenerList();

        for (int i = listeners.length - 2; i >= 0; i -= 2) {

            if (listeners[i] == WorkerOutputListener.class) {

                switch (e.getType()) {

                    case WorkerOutputEvent.COM_GLHOOD :
                        ((WorkerOutputListener) listeners[i + 1]).doComGLHoodOutput(e);

                        break;

                    case WorkerOutputEvent.COM_PLHOOD :
                        ((WorkerOutputListener) listeners[i + 1]).doComPLHoodOutput(e);

                        break;

                    case WorkerOutputEvent.COM_JLHOOD :
                        ((WorkerOutputListener) listeners[i + 1]).doComJLHoodOutput(e);

                        break;

                    case WorkerOutputEvent.ANNEAL :
                        ((WorkerOutputListener) listeners[i + 1]).doAnnealOutput(e);

                        break;

                    case WorkerOutputEvent.PROG_CURVE :
                        ((WorkerOutputListener) listeners[i + 1]).doProgCurveOutput(e);

                        break;
                }
            }
        }
    }

    /**
     * the length of the progressfor this worker
     * @return
     */
    public int getProgLength() {
        return progLength;
    }

    /**
     * the starting value of the progress bar for this worker.
     * @return
     */
    public int getProgStartVal() {
        return progStartVal;
    }

    /**
     * the length of the progressfor this worker
     *
     * @param newVal
     */
    public void setProgLength(int newVal) {
        progLength = newVal;
    }

    /**
     * the starting value of the progress bar for this worker.
     *
     * @param newVal
     */
    public void setProgStartVal(int newVal) {
        progStartVal = newVal;
    }

    /**
     * the parent worker that is delegating a job to this child worker.  Propety
     * change listeners from the parent worker would be added to this child worker for
     * a chained working enviornment.
     * @return
     */
    public Worker getParentWorker() {
        return parentWorker;
    }

    public Worker getChildWorker() {
        return childWorker;
    }

    void setChildWorker(Worker childWorker) {
        this.childWorker = childWorker;
    }
}
